﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;

namespace ECommerce.DAO.SQL
{
    public class Parámetro
    {
        public SqlDbType Tipo;
        public Object Valor;
        public string Nombre;
        public Parámetro(string Nombre, SqlDbType Tipo, Object Valor)
        {
            this.Tipo = Tipo;
            this.Nombre = Nombre;
            this.Valor = Valor;
        }
    }
    public class SqlHelper
    {
        /// <summary>
        /// Devuelve un Datatable con el resultado de un SP.
        /// </summary>
        /// <param name="ConnectionStringName"></param>
        /// <param name="StoreProcedure"></param>
        /// <param name="Parámetros"></param>
        /// <returns></returns>
        public static DataTable Select(string StoreProcedure, ECommerce.DAO.SQL.Parámetro[] Parámetros)
        {
            DataTable dt = new DataTable();
            using (SqlConnection sqlConn = new SqlConnection(App.DbConnStr))
            {
                using (SqlCommand sqlComm = new SqlCommand(StoreProcedure))
                {
                    sqlComm.CommandType = CommandType.StoredProcedure;
                    SqlParameter param;
                    foreach (ECommerce.DAO.SQL.Parámetro Parámetro in Parámetros)
                    {
                        param = new SqlParameter();
                        param.SqlDbType = Parámetro.Tipo;
                        param.Value = Parámetro.Valor;
                        param.ParameterName = Parámetro.Nombre;
                        sqlComm.Parameters.Add(param);
                    }
                    sqlComm.Connection = sqlConn;
                    sqlConn.Open();
                    using (SqlDataReader dr = sqlComm.ExecuteReader())
                    {
                        dt.Load(dr);
                    }
                     sqlConn.Close();
                }
            }
            return dt;
        }
        /// <summary>
        /// Convierte el DataTable a un array de ECommerce.Model.Objeto. Los ECommerce.Model.Objeto pueden ser cualquier objeto heredado, que se cargan según el factory correspondiente.
        /// </summary>
        /// <param name="ConnectionStringName">Nombre de la Conexión definida en el web.config.</param>
        /// <param name="StoreProcedure">Store Procedure que devuelve los objetos.</param>
        /// <param name="Parámetros">Array de ECommerce.DAO.SQL.Parámetro con los parámetros a pasar al SP.</param>
        /// <param name="DynamicType">Type del Objeto que se utiliza para seleccionar el Factory para la carga.</param>
        /// <returns>Devuelve un array de ECommerce.Model.Objeto.</returns>
        public static ECommerce.Model.Objeto[] Get(string StoreProcedure, ECommerce.DAO.SQL.Parámetro[] Parámetros, Type DynamicType)
        {
            ECommerce.Model.Objeto result = new ECommerce.Model.Objeto();
            List<ECommerce.Model.Objeto> results = new List<ECommerce.Model.Objeto>();
            DataTable dt = ECommerce.DAO.SQL.SqlHelper.Select(StoreProcedure, Parámetros.ToArray());
            foreach (DataRow dr in dt.Rows)
            {
                result = ECommerce.DAO.SQL.SqlHelper.GetLoad(dr, DynamicType);
                results.Add(result);
            }
            return results.ToArray();
        }
        /// <summary>
        /// Este método simula un casteo dinámico para ejecutar el .Load(dr) de los objetos.
        /// Agregue un case para cada tipo de nuevo de objeto.
        /// </summary>
        /// <param name="dr">DataRow que contiene los campos para cargar el objeto.</param>
        /// <param name="Tipo">Type del objeto a cargar.</param>
        /// <returns></returns>
        public static ECommerce.Model.Objeto GetLoad(DataRow dr, Type Tipo)
        {
            ECommerce.Model.Objeto result = new ECommerce.Model.Objeto();
            switch (Tipo.ToString())
            { 
                case "ECommerce.Model.Objeto":
                    result.Load(dr);
                    break;
                case "ECommerce.Model.Comercios.Catálogo":
                    ECommerce.Model.Comercios.Catálogo Catálogo = new ECommerce.Model.Comercios.Catálogo();
                    Catálogo.Load(dr);
                    result = Catálogo;
                    break;
                case "ECommerce.Model.Comercios.Comercio":
                    ECommerce.Model.Comercios.Comercio Comercio = new ECommerce.Model.Comercios.Comercio();
                    Comercio.Load(dr);
                    result = Comercio;
                    break;
                case "ECommerce.Model.Comunicaciones.Email":
                    ECommerce.Model.Comunicaciones.Email Email = new ECommerce.Model.Comunicaciones.Email();
                    Email.Load(dr);
                    result = Email;
                    break;
                case "ECommerce.Model.Comunicaciones.Teléfono":
                    ECommerce.Model.Comunicaciones.Teléfono Teléfono = new ECommerce.Model.Comunicaciones.Teléfono();
                    Teléfono.Load(dr);
                    result = Teléfono;
                    break;
                case "ECommerce.Model.Controles.WebControl":
                    ECommerce.Model.Controles.WebControl WebControl = new ECommerce.Model.Controles.WebControl();
                    WebControl.Load(dr);
                    result = WebControl;
                    break;
                case "ECommerce.Model.Contabilidad.Carritos.Carrito":
                    ECommerce.Model.Contabilidad.Carritos.Carrito Carrito = new ECommerce.Model.Contabilidad.Carritos.Carrito();
                    Carrito.Load(dr);
                    result = Carrito;
                    break;
                case "ECommerce.Model.Contabilidad.Carritos.ItemCarrito":
                    ECommerce.Model.Contabilidad.Carritos.ItemCarrito ItemCarrito = new ECommerce.Model.Contabilidad.Carritos.ItemCarrito();
                    ItemCarrito.Load(dr);
                    result = ItemCarrito;
                    break;
                case "ECommerce.Model.Contabilidad.Formularios.Factura":
                    ECommerce.Model.Contabilidad.Formularios.Factura Factura = new ECommerce.Model.Contabilidad.Formularios.Factura();
                    Factura.Load(dr);
                    result = Factura;
                    break;
                case "ECommerce.Model.Contabilidad.Formularios.Pedido":
                    ECommerce.Model.Contabilidad.Formularios.Pedido Pedido = new ECommerce.Model.Contabilidad.Formularios.Pedido();
                    Pedido.Load(dr);
                    result = Pedido;
                    break;
                case "ECommerce.Model.Contabilidad.Formularios.Remito":
                    ECommerce.Model.Contabilidad.Formularios.Remito Remito = new ECommerce.Model.Contabilidad.Formularios.Remito();
                    Remito.Load(dr);
                    result = Remito;
                    break;
                case "ECommerce.Model.Contabilidad.Operaciones.Operación":
                    ECommerce.Model.Contabilidad.Operaciones.Operación Operación = new ECommerce.Model.Contabilidad.Operaciones.Operación();
                    Operación.Load(dr);
                    result = Operación;
                    break;
                case "ECommerce.Model.Contabilidad.Operaciones.TipoOperación":
                    ECommerce.Model.Contabilidad.Operaciones.TipoOperación TipoOperación = new ECommerce.Model.Contabilidad.Operaciones.TipoOperación();
                    TipoOperación.Load(dr);
                    result = TipoOperación;
                    break;
                case "ECommerce.Model.Movimientos.Caja":
                    ECommerce.Model.Contabilidad.Movimientos.Caja Caja = new ECommerce.Model.Contabilidad.Movimientos.Caja();
                    Caja.Load(dr);
                    result = Caja;
                    break;
                case "ECommerce.Model.Movimientos.Mercadería":
                    ECommerce.Model.Contabilidad.Movimientos.Mercadería Mercadería = new ECommerce.Model.Contabilidad.Movimientos.Mercadería();
                    Mercadería.Load(dr);
                    result = Mercadería;
                    break;
                case "ECommerce.Model.Movimientos.Movimiento":
                    ECommerce.Model.Contabilidad.Movimientos.Movimiento Movimiento = new ECommerce.Model.Contabilidad.Movimientos.Movimiento();
                    Movimiento.Load(dr);
                    result = Movimiento;
                    break;
                case "ECommerce.Model.Personas.Cliente":
                    ECommerce.Model.Personas.Cliente Cliente = new ECommerce.Model.Personas.Cliente();
                    Cliente.Load(dr);
                    result = Cliente;
                    break;
                case "ECommerce.Model.Seguridad.Perfil":
                    ECommerce.Model.Seguridad.Perfil Perfil = new ECommerce.Model.Seguridad.Perfil();
                    Perfil.Load(dr);
                    result = Perfil;
                    break;
                case "ECommerce.Model.Personas.Persona":
                    ECommerce.Model.Personas.Persona Persona = new ECommerce.Model.Personas.Persona();
                    Persona.Load(dr);
                    result = Persona;
                    break;
                case "ECommerce.Model.Personas.Proveedor":
                    ECommerce.Model.Personas.Proveedor Proveedor = new ECommerce.Model.Personas.Proveedor();
                    Proveedor.Load(dr);
                    result = Proveedor;
                    break;
                case "ECommerce.Model.Personas.Usuario":
                    ECommerce.Model.Personas.Usuario Usuario = new ECommerce.Model.Personas.Usuario();
                    Usuario.Load(dr);
                    result = Usuario;
                    break;
                case "ECommerce.Model.Productos.CódigosProducto.CódigoProducto":
                    ECommerce.Model.Productos.CódigosProducto.CódigoProducto CódigoProducto = new ECommerce.Model.Productos.CódigosProducto.CódigoProducto();
                    CódigoProducto.Load(dr);
                    result = CódigoProducto;
                    break;
                case "ECommerce.Model.Productos.CódigosProducto.TipoCódigoProducto":
                    ECommerce.Model.Productos.CódigosProducto.TipoCódigoProducto TipoCódigoProducto = new ECommerce.Model.Productos.CódigosProducto.TipoCódigoProducto();
                    TipoCódigoProducto.Load(dr);
                    result = TipoCódigoProducto;
                    break;
                case "ECommerce.Model.Productos.Familia":
                    ECommerce.Model.Productos.Producto Familia = new ECommerce.Model.Productos.Producto();
                    Familia.Load(dr);
                    result = Familia;
                    break;
                case "ECommerce.Model.Productos.Package":
                    ECommerce.Model.Productos.Producto Package = new ECommerce.Model.Productos.Producto();
                    Package.Load(dr);
                    result = Package;
                    break;
                case "ECommerce.Model.Productos.Precios.Moneda":
                    ECommerce.Model.Productos.Producto Moneda = new ECommerce.Model.Productos.Producto();
                    Moneda.Load(dr);
                    result = Moneda;
                    break;
                case "ECommerce.Model.Productos.Precios.Precio":
                    ECommerce.Model.Productos.Producto Precio = new ECommerce.Model.Productos.Producto();
                    Precio.Load(dr);
                    result = Precio;
                    break;
                case "ECommerce.Model.Productos.Precios.TipoPrecio":
                    ECommerce.Model.Productos.Producto TipoPrecio = new ECommerce.Model.Productos.Producto();
                    TipoPrecio.Load(dr);
                    result = TipoPrecio;
                    break;
                case "ECommerce.Model.Productos.Producto":
                    ECommerce.Model.Productos.Producto Producto = new ECommerce.Model.Productos.Producto();
                    Producto.Load(dr);
                    result = Producto;
                    break;
                case "ECommerce.Model.Ubicaciones.Barrio":
                    ECommerce.Model.Productos.Producto Barrio = new ECommerce.Model.Productos.Producto();
                    Barrio.Load(dr);
                    result = Barrio;
                    break;
                case "ECommerce.Model.Ubicaciones.Calle":
                    ECommerce.Model.Ubicaciones.Calle Calle = new ECommerce.Model.Ubicaciones.Calle();
                    Calle.Load(dr);
                    result = Calle;
                    break;
                case "ECommerce.Model.Ubicaciones.Ciudad":
                    ECommerce.Model.Ubicaciones.Ciudad Ciudad = new ECommerce.Model.Ubicaciones.Ciudad();
                    Ciudad.Load(dr);
                    result = Ciudad;
                    break;
                case "ECommerce.Model.Ubicaciones.Dirección":
                    ECommerce.Model.Ubicaciones.Dirección Dirección = new ECommerce.Model.Ubicaciones.Dirección();
                    Dirección.Load(dr);
                    result = Dirección;
                    break;
                case "ECommerce.Model.Ubicaciones.Municipio":
                    ECommerce.Model.Ubicaciones.Municipio Municipio = new ECommerce.Model.Ubicaciones.Municipio();
                    Municipio.Load(dr);
                    result = Municipio;
                    break;
                case "ECommerce.Model.Ubicaciones.País":
                    ECommerce.Model.Ubicaciones.País País = new ECommerce.Model.Ubicaciones.País();
                    País.Load(dr);
                    result = País;
                    break;
                case "ECommerce.Model.Ubicaciones.Provincia":
                    ECommerce.Model.Ubicaciones.Provincia Provincia = new ECommerce.Model.Ubicaciones.Provincia();
                    Provincia.Load(dr);
                    result = Provincia;
                    break;
                default:
                    throw new Exception("Falta definir " + Tipo.ToString() + " en el Switch del método GetLoad(...) de la clase ECommerce.DAO.SQL.SqlHelper");
            }
            return result;
        }
        /// <summary>
        /// Realiza un Insert en la base especificada, utilizando el SP Especificado.
        /// </summary>
        /// <param name="ConnectionStringName"></param>
        /// <param name="StoreProcedure"></param>
        /// <param name="Parámetros"></param>
        /// <returns>Devuelve el Id del objeto Creado</returns>
        public static Int32 Insert(string StoreProcedure, ECommerce.DAO.SQL.Parámetro[] Parámetros)
        {
            object result;
            using (SqlConnection sqlConn = new SqlConnection(App.DbConnStr))
            {
                using (SqlCommand sqlComm = new SqlCommand(StoreProcedure))
                {
                    sqlComm.CommandType = CommandType.StoredProcedure;
                    SqlParameter param = new SqlParameter();
                    foreach (ECommerce.DAO.SQL.Parámetro Parámetro in Parámetros)
                    {
                        param = new SqlParameter();
                        param.SqlDbType = Parámetro.Tipo;
                        param.Value = Parámetro.Valor;
                        param.ParameterName = Parámetro.Nombre;
                        sqlComm.Parameters.Add(param);
                    }
                    sqlComm.Connection = sqlConn;
                    sqlConn.Open();
                    result = sqlComm.ExecuteScalar();
                    sqlConn.Close();
                }
            }
            if (result != null)
                return Convert.ToInt32(result);
            else 
                return 0;
        }
        /// <summary>
        /// Ejecuta un SP que no devuelve resultados.
        /// </summary>
        /// <param name="ConnectionStringName"></param>
        /// <param name="StoreProcedure"></param>
        /// <param name="Parámetros"></param>
        public static void Execute(string StoreProcedure, ECommerce.DAO.SQL.Parámetro[] Parámetros)
        {
            using (SqlConnection sqlConn = new SqlConnection(App.DbConnStr))
            {
                using (SqlCommand sqlComm = new SqlCommand(StoreProcedure))
                {
                    sqlComm.CommandType = CommandType.StoredProcedure;
                    SqlParameter param = new SqlParameter();
                    foreach (ECommerce.DAO.SQL.Parámetro Parámetro in Parámetros)
                    {
                        param = new SqlParameter();
                        param.SqlDbType = Parámetro.Tipo;
                        param.Value = Parámetro.Valor;
                        param.ParameterName = Parámetro.Nombre;
                        sqlComm.Parameters.Add(param);
                    }
                    sqlComm.Connection = sqlConn;
                    sqlConn.Open();
                    sqlComm.ExecuteScalar();
                    sqlConn.Close();
                }
            }
        }
    }
}
